package model.bo;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import model.entidade.CPF;
import model.entidade.Empregado;

public class EmpregadoBO extends BaseBO<Empregado> {

	private static EmpregadoBO instancia;
	private static List<Empregado> listaEmpregados = null;

	/**
	 * Método executado para garantir a existência de apenas uma instância dessa classe (Singleton).
	 * 
	 * @return uma instância da classe EmpregadoBO 
	 * @author Zeno
	 * 
	 */
	public static EmpregadoBO getInstance() {
		if (instancia == null) {
			instancia = new EmpregadoBO();
			listaEmpregados = new ArrayList<Empregado>();
		}
		return instancia;
	}

	/**
	 * Método executado para incluir determinado empregado na lista de empregados.
	 * 
	 * @param empregado
	 * @throws Exception
	 * @author Zeno
	 * 
	 */
	@Override
	public void incluir(Empregado empregado) throws Exception {
		listaEmpregados.add(empregado);
	}

	/**
	 * Método executado para remover o antigo empregado e adicionar o empregado alterado novamente na lista.
	 * 
	 * @param antigoEmpregado que é o empregado que será removido
	 * @param novoEmpregado que é o empregado que será adicionado
	 * @throws Exception
	 * @author Zeno
	 * 
	 */
	@Override
	public void alterar(Empregado antigoEmpregado, Empregado novoEmpregado) throws Exception {
		listaEmpregados.remove(antigoEmpregado);
		listaEmpregados.add(novoEmpregado);
	}

	/**
	 * Método executado para excluir determinado empregado na lista de empregados.
	 * 
	 * @param empregado
	 * @throws Exception
	 * @author Zeno
	 * 
	 */
	@Override
	public void excluir(Empregado empregado) throws Exception {
		listaEmpregados.remove(empregado);
	}

	/**
	 * Método executado para listar todos os empregados.
	 * 
	 * @return Lista de empregados
	 * @throws Exception
	 * @author Zeno
	 * 
	 */
	@Override
	public List<Empregado> listar() throws Exception {
		return listaEmpregados;
	}

	/**
	 * Método executado para retornar um empregado dado seu identificador.
	 * 
	 * @param id
	 * @return empregado
	 * @throws Exception
	 * @author Zeno
	 * 
	 */
	public Empregado consultar(Long id) throws Exception {
		return listaEmpregados.get(id.intValue());
	}

	/**
	 * Método executado para retornar um empregado dado seu cpf.
	 * 
	 * @param cpf
	 * @return empregado
	 * @throws Exception
	 * @author Rúben
	 * 
	 */
	public Empregado consultarCpf(String cpf) throws Exception {

		Empregado empr= new Empregado(null, "", null, null, cpf, "", "", "");
		List <Empregado> lista = EmpregadoBO.getInstance().consultaEmpregado(empr);
		Empregado empregado = lista.get(0);
		return empregado;
	}

	/**
	 * Método executado para validar as informações de empregado antes de ser incluído.
	 * 
	 * @param Empregado a ser incluido
	 * @throws Exception, EmpregadoException
	 * @author Zeno
	 * 
	 */
	public void incluiEmpregado(Empregado empregado) throws Exception, EmpregadoException {

		if (validaDadosEmpregadoAntesSubmeter(empregado) && validaNaoExistenciaDeCpf(empregado.getCpf())) {

			EmpregadoBO.getInstance().incluir(empregado);

		}                   

	}

	/**
	 * Método executado para validar as informações de empregado antes de ser alterado.
	 * 
	 * @param Empregado a ser incluido
	 * @throws Exception, EmpregadoException
	 * @author Zeno
	 * 
	 */
	public void alteraEmpregado(Empregado antigoEmpregado, Empregado novoEmpregado) throws Exception, EmpregadoException {

		if (validaDadosEmpregadoAntesSubmeter(antigoEmpregado)) {

			EmpregadoBO.getInstance().alterar(antigoEmpregado, novoEmpregado);

		}                   

	}

	private boolean validaDadosEmpregadoAntesSubmeter(
			Empregado empregado) throws EmpregadoException,
			ParseException {
		
		EmpregadoValidationHelper empregadoValidationHelper = new EmpregadoValidationHelper(empregado);
		
		
		return empregadoValidationHelper.validaCampos();

	
	}

	/**
	 * Método executado para verificar igualdade de determinado empregado na lista de empregados.
	 * 
	 * @param Empregado a ser consultado
	 * @return Lista com todos os empregados semelhantes a ele
	 * @throws Exception
	 * @author Zeno
	 * 
	 */
	public List<Empregado> consultaEmpregado(Empregado empregadoConsultado) throws Exception {

		List<Empregado> listaEmpregadosConsultados = new ArrayList<Empregado>();

		for (int i = 0; i < listaEmpregados.size(); i++) {

			if (!empregadoConsultado.getNome().equals("")) {
				if (!empregadoConsultado.getNome().equals(listaEmpregados.get(i).getNome()))
					continue;
			}

			if (empregadoConsultado.getSexo() != null) {
				if (empregadoConsultado.getSexo() != listaEmpregados.get(i).getSexo())
					continue;
			}

			if (empregadoConsultado.getSalario() != null) {
				if (empregadoConsultado.getSalario().compareTo(listaEmpregados.get(i).getSalario()) != 0)
					continue;
			}

			if (!empregadoConsultado.getCpf().equals("")) {
				if (!empregadoConsultado.getCpf().equals(listaEmpregados.get(i).getCpf()))
					continue;
			}

			if (!empregadoConsultado.getDataNascimento().equals("")) {
				if (!empregadoConsultado.getDataNascimento().equals(listaEmpregados.get(i).getDataNascimento()))
					continue;
			}

			if (!empregadoConsultado.getDataAdmissao().equals("")) {
				if (!empregadoConsultado.getDataAdmissao().equals(listaEmpregados.get(i).getDataAdmissao()))
					continue;
			}

			if (!empregadoConsultado.getDataDesligamento().equals("")) {
				if (!empregadoConsultado.getDataDesligamento().equals(listaEmpregados.get(i).getDataDesligamento()))
					continue;
			}

			listaEmpregadosConsultados.add(listaEmpregados.get(i));

		}

		return listaEmpregadosConsultados;

	}



	

	/**
	 * Método executado para verificar se os campos obrigatórios estão preenchidos.
	 * São campos obrigatórios: nome, sexo, salário atual, CPF, data de nascimento e data de admissão.
	 *
	 * @param empregado do tipo Empregado
	 * @return Booleano que indica se estão preenchidos ou não
	 * @author Rúben, Zeno
	 *
	 */
	public boolean verificaCamposObrigatorios(Empregado empregado) throws EmpregadoException
	{
		EmpregadoValidationHelper empregadoHelper = new EmpregadoValidationHelper(empregado);

		if (empregadoHelper.validaCamposObrigatorios())
			return true;
		else		
			throw new EmpregadoException("Os campos obrigatorio nao foram preenchidos.");

	}


	/**
	 * Método que verifica se o CPF inserido é um CPF válido.
	 * 
	 * @param CPF do empregado a ser inserido
	 * @return Booleano que indica se esse CPF já está cadastrado
	 * @author Zeno
	 * 
	 */

	public  boolean validaNaoExistenciaDeCpf(String cpf) throws EmpregadoException {

		for (int i = 0; i < listaEmpregados.size(); i++) {
			if (listaEmpregados.get(i).getCpf().equals(cpf)) {
				throw new EmpregadoException("Esse CPF ja esta cadastrado.");
			}
		}

		return true;

	}

	/**
	 * Método calcula a idade da pessoa na data atual (dia de hoje)
	 * 
	 * @param Data de nascimento
	 * @return inteiro com a idade
	 * @author Rúben, Wanessa, Arthur
	 * 
	 */

	public int calculaIdade(String dataNascimento) throws EmpregadoException, ParseException
	{
		int idade=0;
		SimpleDateFormat formatar = new SimpleDateFormat("dd/MM/yyyy");

		Date dataNasc = formatar.parse(dataNascimento);
		Calendar hoje = Calendar.getInstance();

		Date dataNascVerificacao= (Date)dataNasc.clone();

		dataNascVerificacao.setYear(hoje.getTime().getYear());

		if (dataNascVerificacao.compareTo(hoje.getTime())<= 0){ //ja fez aniversario esse ano
			idade = hoje.getTime().getYear() - dataNasc.getYear();

		}
		else{

			idade = (hoje.getTime().getYear() - dataNasc.getYear()) - 1;
		}


		return idade;
	}

}
